package com.logic.landseaserver.service.impl;

import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.common.util.QueryUtil;
import com.logic.common.util.SysUtil;
import com.logic.common.ws.dto.system.UserPassChangeDTO;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.config.WeixinConfiguration;
import com.logic.landseaserver.common.enums.SendMsgCodeEnum;
import com.logic.landseaserver.common.exception.LandseaBusinessException;
import com.logic.landseaserver.common.util.HttpRequestClient;
import com.logic.landseaserver.domain.Customer;
import com.logic.landseaserver.domain.VerificationCode;
import com.logic.landseaserver.persistence.read.ClientUserReadMapper;
import com.logic.landseaserver.persistence.read.CustomerReadMapper;
import com.logic.landseaserver.persistence.write.CustomerVersionWriteMapper;
import com.logic.landseaserver.persistence.write.CustomerWriteMapper;
import com.logic.landseaserver.service.ICustomer;
import com.logic.landseaserver.service.ISendSmsService;
import com.logic.landseaserver.service.IUser;
import com.logic.landseaserver.ws.dto.CustomerDTO;
import com.logic.landseaserver.ws.dto.UserDTO;
import com.logic.landseaserver.ws.request.RegisterReq;
import com.logic.landseaserver.ws.response.UserInfoResponse;
import com.logic.landseaserver.ws.response.WeixinInfoResponse;
import com.logic.system.domain.User;
import com.logic.system.persistence.read.UserReadMapper;
import com.logic.system.persistence.write.UserWriteMapper;
import com.logic.system.service.IConfigurationService;
import com.logic.system.service.ITaskService;
import com.logic.system.service.IUserService;
import com.logic.system.service.impl.ConfigurationService;
import net.sf.json.JSONObject;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;

/**
 * @Author: Quintina.Yu
 * @Date: 2017/5/23
 * @Description: 用户
 */
@Service
public class ClientUserServiceImpl implements IUser
{
    private static final Logger LOG = LoggerFactory.getLogger(ClientUserServiceImpl.class);
    
    @Autowired
    private UserReadMapper userReadMapper;
    
    @Autowired
    private ClientUserReadMapper clientUserReadMapper;
    
    @Autowired
    private CustomerReadMapper customerReadMapper;
    
    @Autowired
    private UserWriteMapper userWriteMapper;
    
    @Autowired
    private CustomerWriteMapper customerWriteMapper;
    @Autowired
    private ICustomer customerService;
    @Autowired
    private CustomerVersionWriteMapper customerVersionWriteMapper;
    @Autowired
    private ISendSmsService sendSmsService;
    
    @Autowired
    private IUserService userService;
    
    @Autowired
    private ITaskService taskService;
    
    @Autowired
    private WeixinConfiguration weixinConfiguration;
    
    private static final Logger log = LoggerFactory.getLogger(ClientUserServiceImpl.class);
    
    @Autowired
    IConfigurationService configurationService;
    
    @Override
    public synchronized int register(RegisterReq req)
        throws BusinessException
    {
        validateRegister(req);
        // 校验验证码
        VerificationCode verification = new VerificationCode();
        verification.setCellPhone(req.getLoginId());
        verification.setVerificationCode(req.getVerifyCode());
        verification.setOper(SendMsgCodeEnum.register.getCode());
        sendSmsService.checkVerification(verification);
        User pUser = new User();
        pUser.setLoginId(req.getLoginId());
        User existUser = itExistUser(pUser);
        if (existUser != null)
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_LOGIN_HASONE);
        }
        
        UserDTO userDTO = new UserDTO();
        userDTO.setLoginId(req.getLoginId());
        userDTO.setPassword(req.getPassword());
        userDTO.setUpdatePwdFlag(true);
        CustomerDTO customerDTO = new CustomerDTO();
        customerDTO.setPhone(req.getLoginId());
        userDTO.setCustomerDTO(customerDTO);
        insert(userDTO);
        return 0;
    }
    
    @Override
    public int updateUserPwd(RegisterReq req)
        throws BusinessException
    {
        validateRegister(req);
        // 判断是否有此用户
        User pUser = new User();
        pUser.setLoginId(req.getLoginId());
        User existUser = itExistUser(pUser);
        if (existUser == null)
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_LOGIN_NONE);
        }
        if (existUser.getLocked().equals("1") || existUser.getDisabled().equals("1") || existUser.getDeleted())
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.USER_UPDATEUSER_ALREADY_DISABLE);
        }
        // 校验验证码
        VerificationCode verification = new VerificationCode();
        verification.setCellPhone(req.getLoginId());
        verification.setVerificationCode(req.getVerifyCode());
        verification.setOper(SendMsgCodeEnum.updatePsd.getCode());
        sendSmsService.checkVerification(verification);
        
        UserDTO userDTO = new UserDTO();
        userDTO.setId(existUser.getId());
        userDTO.setPassword(req.getPassword());
        userDTO.setUpdatePwdFlag(true);
        CustomerDTO customerDTO = new CustomerDTO();
        customerDTO.setPhone(req.getLoginId());
        userDTO.setCustomerDTO(customerDTO);
        update(userDTO);
        return 0;
    }
    
    private Boolean validateRegister(RegisterReq req)
        throws LandseaBusinessException
    {
        if (StringUtils.isEmpty(req.getLoginId()))
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_LOGINID_ISNULL);
        }
        if (StringUtils.isEmpty(req.getVerifyCode()))
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_CODE_ISNULL);
        }
        if (StringUtils.isEmpty(req.getPassword()))
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_PASSWORD_ISNULL);
        }
        return true;
    }
    
    @Override
    public int insert(Object o)
        throws BusinessException
    {
        UserDTO userDTO = (UserDTO)o;
        User user = UserDTO.fromDTOtoUser(userDTO);
        
        if (StringUtils.isEmpty(userDTO.getLoginId()))
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.USER_CREATE_LOGIN_IS_NULL);
        }
        if (userService.canPWDExpired() && !StringUtils.isEmpty(user.getPassword()))
        {
            user.setPwdExpiredDate(getPWDExpiredDate());
        }
        user.setDisabled(false);
        user.setSystemic(false);
        user.setLocked(false);
        user.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        userWriteMapper.insertSelective(user);
        CustomerDTO customerDTO = userDTO.getCustomerDTO();
        if (customerDTO != null)
        {
            Customer customer = CustomerDTO.fromDTOtoCustomer(customerDTO);
            customer.setUserId(user.getId());
            customer.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            customerWriteMapper.insertSelective(customer);

            try {
                customerService.insertCustomerVersion(customer.getId(),null);
            } catch (Exception e) {
                LOG.error("insertCustomerVersion error", e);
            }

        }
        return user.getId();
    }
    
    @Override
    public User get(Integer id)
        throws BusinessException
    {
        User user = clientUserReadMapper.selectByPrimaryKey(id);
        return user;
    }
    
    @Override
    public UserInfoResponse getInfo()
        throws BusinessException
    {
        Integer userId = SecurityUtils.getCurrentLogin().getUserId();
        if (userId == null)
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.TOKEN_IS_NULL);
        }
        
        return customerReadMapper.selectCustomerInfo(userId);
    }
    
    @Override
    public WeixinInfoResponse getOpenId(String code)
        throws LandseaBusinessException
    {
        Integer userId = SecurityUtils.getCurrentLogin().getUserId();
        WeixinInfoResponse response = new WeixinInfoResponse();
        log.info("updateMyOpenId start");
        if (!org.apache.commons.lang.StringUtils.isEmpty(code))
        {
            // 获取openid
            String openId = "";
            String accessToken = "";
            String appid = weixinConfiguration.getAppid();
            String secret = weixinConfiguration.getAppsect();
            String url = weixinConfiguration.getQueryOpenIdUrl();
            url = url.replace("APPID", appid).replace("SECRET", secret).replace("CODE", code);
            String json = HttpRequestClient.postHttpsRequest(url, null);
            JSONObject obj = JSONObject.fromObject(json);
            log.info("code为：" + code + "     获取openid的json为：" + obj.toString());
            try
            {
                openId = obj.getString("openid");
                accessToken = obj.getString("access_token");
            }
            catch (Exception e)
            {
                openId = "";
            }
            if (org.apache.commons.lang.StringUtils.isNotEmpty(openId))
            {
                
                JSONObject objInfo = (JSONObject)queryUserInfoByOpenId(accessToken, openId);
                try
                {
                    response.setImgUrl(objInfo.getString("headimgurl"));
                    response.setNickName(objInfo.getString("nickname"));
                    response.setOpenId(openId);
                    
                }
                catch (Exception e)
                {
                    log.info("获取openId失败");
                }
            }
        }
        return response;
    }
    
    @Override
    public void updateUserOpenId(String code, Integer userId)
            throws Exception
    {
        log.info("userId++++++:" + userId + "||code++++++++++++:" + code);
        if (code == null || userId == null)
        {
            return;
        }
        WeixinInfoResponse response = getOpenId(code);
        if (response != null)
        {
            log.info("imgUrl++++++:" + response.getImgUrl() + "||openId++++++++++++:" + response.getOpenId());
            Customer customer = new Customer();
            customer.setUserId(userId);
            customer.setImgUrl(response.getImgUrl());
            customer.setOpenId(response.getOpenId());
            customer.setNickName(response.getNickName());
            customer.updateCommonInfo(-1);
            customerWriteMapper.updateByUser(customer);
            customerService.insertCustomerVersion(null,userId);
        }
    }
    
    @Override
    public Boolean updatePassword(UserPassChangeDTO userPassChangeDTO)
        throws LandseaBusinessException
    {
        
        Integer userId = SecurityUtils.getCurrentLogin().getUserId();
        if (userId == null || userId == -1)
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.TOKEN_IS_NULL);
        }
        Boolean ret = false;
        userPassChangeDTO.setUser_id(userId);
        String old_password = userPassChangeDTO.getOld_password();
        String new_password = userPassChangeDTO.getNew_password();
        User user = userReadMapper.selectByPrimaryKey(userPassChangeDTO.getUser_id());
        String old_password_MD5 = user.getPassword();
        if (old_password != null)
        {
            if (SysUtil.MD5Digest(old_password).equals(old_password_MD5))
            {
                user.updateCommonInfo(userPassChangeDTO.getUser_id());
                user.setPassword(SysUtil.MD5Digest(new_password));
                user.setUpdatePwdFlag(true);
                if (userService.canPWDExpired())
                {
                    user.setPwdExpiredDate(getPWDExpiredDate());
                }
                int success = userWriteMapper.updateByPrimaryKeySelective(user);
                if (success == 1)
                    ret = true;
            }
            else
            {
                throw new LandseaBusinessException(LandseaErrorMessageEnum.OLD_PASSWORD_IS_ERROR);
            }
        }
        return ret;
        
    }
    
    private Object queryUserInfoByOpenId(String accessToken, String openId)
    {
        if (org.apache.commons.lang.StringUtils.isEmpty(openId))
        {
            return null;
        }
        else
        {
            String queryInfoUrl = weixinConfiguration.getQueryUserInfoUrl();
            queryInfoUrl = queryInfoUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
            HttpMethod method = new PostMethod(queryInfoUrl);
            HttpClient httpclient = new HttpClient();
            
            try
            {
                httpclient.executeMethod(method);
            }
            catch (HttpException e)
            {
                LOG.error("queryUserInfoByOpenId error.", e);
            }
            catch (IOException e)
            {
                LOG.error("queryUserInfoByOpenId error.", e);
            }
            
            String result = "";
            try
            {
                result = new String(method.getResponseBody(), "utf-8");
            }
            catch (UnsupportedEncodingException e)
            {
                LOG.error("queryUserInfoByOpenId error.", e);
            }
            catch (IOException e)
            {
                LOG.error("queryUserInfoByOpenId error.", e);
            }
            LOG.info("getWeiXinUserInfo result = " + result);
            
            JSONObject objInfo = JSONObject.fromObject(result);
            return objInfo;
        }
        
    }
    
    private Date getPWDExpiredDate()
    {
        
        Double pwdExpDays = configurationService.getDoubleValue(ConfigurationService.SYS_PWD_CFG_D_PWD_EXP_DAYS);
        if (pwdExpDays == null)
        {
            pwdExpDays = 30 * 3.0;
        }
        
        return new Date(taskService.getCurrentTime().getTime() + (long)(1000 * 60 * 60 * 24 * pwdExpDays));
    }
    
    @Override
    public void update(Object o)
        throws BusinessException
    {
        UserDTO userDTO = (UserDTO)o;
        User user = UserDTO.fromDTOtoUser(userDTO);
        
        User systemUser = clientUserReadMapper.selectByPrimaryKey(user.getId());
        if (systemUser == null)
        {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_LOGIN_NONE);
        }
        
        Customer customer = systemUser.getCustomer();
        if (customer == null)
        {
            Customer uCustomer = user.getCustomer();
            uCustomer.setUserId(user.getId());
            uCustomer.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            customerWriteMapper.insertSelective(customer);
        }
        else
        {
            Customer uCustomer = user.getCustomer();
            uCustomer.setUserId(user.getId());
            uCustomer.setId(customer.getId());
            uCustomer.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            customerWriteMapper.updateByPrimaryKeySelective(uCustomer);
        }
        if (user.getPassword() != null && !user.getPassword().equals(""))
        {
            if (userService.canPWDExpired())
            {
                user.setPwdExpiredDate(getPWDExpiredDate());
            }
        }
        user.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        userWriteMapper.updateByPrimaryKeySelective(user);
        try {
            customerService.insertCustomerVersion(null,user.getId());
        } catch (Exception e) {
            LOG.error("insertCustomerVersion error", e);
        }
    }
    
    @Override
    public void delete(String s)
        throws BusinessException
    {
        
    }
    
    @Override
    public List<?> query(QueryUtil queryUtil)
    {
        return null;
    }
    
    @Override
    public Boolean validate(Object o)
        throws BusinessException
    {
        return null;
    }
    
    @Override
    public Boolean validateForInsert(Object o)
        throws BusinessException
    {
        
        return null;
    }
    
    @Override
    public Boolean validateForUpdate(Object o)
        throws BusinessException
    {
        return null;
    }
    
    @Override
    public Boolean validateForDelete(Object o)
        throws BusinessException
    {
        return null;
    }
    
    @Override
    public User itExistUser(User user)
    {
        return clientUserReadMapper.itExistUser(user);
    }
}
